#include <sstream>
#include <iostream>
using namespace std;

#define pdt_throw \
    throw PDTException::pdt_throw_ex(__FILE__,__PRETTY_FUNCTION__,__LINE__) <<

typedef enum {
    PDTNullValEx=1,
    PDTConstTypeEx,
    PDTSequenceRangeEx,
    PDTIndexNotEvaluatedEx,
    PDTDivideByZeroEx,
    PDTNotImplementedEx,
    PDTMemoryEx,
    PDTNotResolvedEx,
    
   PDTLastNodeException
} PDTNodeException;

typedef enum {
    PDTFunctionNotFoundEx,
    PDTBehaviorsNotFoundEx,
    PDTReturnStatementEx,

    PDTCheckSpecLastEx,
} PDTCheckSpecException;

class PDTException : public stringstream {
    public:
        PDTException();
        PDTException(PDTException & e);
        PDTException & operator << (PDTNodeException e);
        PDTException & operator() (PDTNodeException e) {
            const char * str;
            switch (e) {
                case PDTNullValEx: str = "PDTNullValEx";break;
                case PDTConstTypeEx: str = "PDTConstTypeEx";break;
                case PDTSequenceRangeEx: str = "PDTSequenceRangeEx";break;
                case PDTIndexNotEvaluatedEx: str = "PDTIndexNotEvaluatedEx";break;
                case PDTDivideByZeroEx: str = "PDTDivideByZeroEx";break;
                case PDTNotImplementedEx: str = "PDTNotImplementedEx";break;
                case PDTMemoryEx: str = "PDTMemoryEx";break;
                case PDTNotResolvedEx: str = "PDTNotResolvedEx";break;
                default: str = "UnknownNodeEx";                       
            }
            (*this)<<"[" << e << "] " << str;
            return *this;
        }

        PDTException & operator << (PDTCheckSpecException e) ;
        PDTException & operator() (PDTCheckSpecException e) {
            const char * str;
            switch(e) {
                case PDTFunctionNotFoundEx: str = "PDTFunctionNotFoundEx";break;
                case PDTBehaviorsNotFoundEx: str = "PDTBehaviorsNotFoundEx";break;
                case PDTReturnStatementEx: str = "PDTReturnStatementEx";break;
                default: str = "UnknownCheckSpecEx"; 
            }
            (*this)<<"[" << e << "] " << str;
            return *this;
        }
        static PDTException & pdt_throw_ex(const char * ff,const char * fc, int ll);
};

